package com.eptok.gw.szcups.cups;

import org.apache.mina.util.ExpirationListener;
import org.apache.mina.util.ExpiringMap;

import ys8583.parse.IOMessage;

import com.eptok.gw.szcups.common.GateWayConstant;
import com.eptok.gw.szcups.common.PropertyLoader;
import com.eptok.gw.szcups.cups.codec.ClientCodecFactory;
import com.eptok.gw.szcups.cups.codec.ServerCodecFactory;
import com.eptok.gw.szcups.cups.handler.ActiveMerClientHandler;
import com.eptok.gw.szcups.cups.handler.ActiveMerServerHandler;
import com.eptok.gw.szcups.cups.handler.ChanClientHandler;
import com.eptok.gw.szcups.cups.handler.ChanServerHandler;
import com.eptok.gw.szcups.cups.handler.PassiveMerClientHandler;
import com.eptok.gw.szcups.cups.handler.PassiveMerServerHandler;
import com.eptok.gw.szcups.socket.client.agent.ClientConfig;
import com.eptok.gw.szcups.socket.client.factory.ClientFactory;
import com.eptok.gw.szcups.socket.server.AsynServer;
import com.eptok.gw.szcups.socket.server.ServerConfig;

/**
 * 银联通讯控制器
 * 
 *@author:heqishan, Email:heqishan@gmail.com
 *2013-3-5 下午02:51:47
 */
public class CupsMessageControl {
	
	public static final String CHAN_CLIENT_KEY = "CHAN_CLIENT";
	private static final String CHAN_CLIENT_NAME = "渠道客户端";
	private static final String CHAN_SERVER_NAME = "渠道服务端";
	
	public static final String ACTIVE_MERCHAN_CLIENT_KEY = "ACTIVE_MERCHAN_CLIENT";
	private static final String ACTIVE_MERCHAN_CLIENT_NAME = "渠道代理商客户端";
	private static final String ACTIVE_MERCHAN_SERVER_NAME = "渠道代理商服务端";
	
	public static final String PASSIVE_MERCHAN_CLIENT_KEY = "PASSIVE_MERCHAN_CLIENT";
	private static final String PASSIVE_MERCHAN_CLIENT_NAME = "SP服务提供商客户端";
	private static final String PASSIVE_MERCHAN_SERVER_NAME = "SP服务提供商服务端";
	
	private AsynServer chanServer;
	private AsynServer activeMerServer;
	private AsynServer passiveMerServer;
	
	private static CupsMessageControl cupsMessageContorl = new CupsMessageControl();
	
	private ExpiringMap<String, IOMessage> chanMessageMap;			//渠道数据保存池
	private ExpiringMap<String, IOMessage> activeMerMessageMap;		//商户(银盛主动)数据保存池
	
	private CupsMessageControl(){}
	
	public static CupsMessageControl getInstance(){
		return cupsMessageContorl;
	}
	
	public void initialized() throws Exception{
		
		//建立渠道数据保存池
		chanMessageMap = new ExpiringMap<String, IOMessage>(GateWayConstant.EXPIRINT_TIMEOUT,
				GateWayConstant.EXPIRINT_INTERVAL);
		chanMessageMap.addExpirationListener(new ExpirationCupsMessageListener());
		chanMessageMap.getExpirer().startExpiring();
		
		activeMerMessageMap = new ExpiringMap<String, IOMessage>(GateWayConstant.EXPIRINT_TIMEOUT,
				GateWayConstant.EXPIRINT_INTERVAL);
		activeMerMessageMap.addExpirationListener(new ExpirationCupsMessageListener());
		activeMerMessageMap.getExpirer().startExpiring();
		
		//初始化客户端管理池
		ClientFactory.getInstance().initiation();

		//启动渠道服务端监听
		ServerConfig chanServerConfig = new ServerConfig();
		chanServerConfig.setHost(PropertyLoader.getInstance().getLocalIp());
		chanServerConfig.setPort(PropertyLoader.getInstance().getChanServerPort());
		chanServerConfig.setCodecFactory(new ServerCodecFactory(CHAN_SERVER_NAME));
		chanServerConfig.setIoHandlerAdapter(new ChanServerHandler(CHAN_SERVER_NAME));
		chanServer = new AsynServer(chanServerConfig);
		chanServer.startListen();
		
		//创建渠道客户端连接实例
		ClientConfig chanClientConfig = new ClientConfig(CHAN_CLIENT_KEY);
		chanClientConfig.setHost(PropertyLoader.getInstance().getChanClientIp());
		chanClientConfig.setPort(PropertyLoader.getInstance().getChanClientPort());
		chanClientConfig.setCodecFactory(new ClientCodecFactory(CHAN_CLIENT_NAME));
		chanClientConfig.setIoHandlerAdapter(new ChanClientHandler(CHAN_CLIENT_NAME));
		ClientFactory.getInstance().createClient(chanClientConfig);
		
		//启动商户(银联主动)服务端监听
		ServerConfig passiveMerServerConfig = new ServerConfig();
		passiveMerServerConfig.setHost(PropertyLoader.getInstance().getLocalIp());
		passiveMerServerConfig.setPort(PropertyLoader.getInstance().getPassiveMerServerPort());
		passiveMerServerConfig.setCodecFactory(new ServerCodecFactory(PASSIVE_MERCHAN_SERVER_NAME));
		passiveMerServerConfig.setIoHandlerAdapter(new PassiveMerServerHandler(PASSIVE_MERCHAN_SERVER_NAME));
		passiveMerServer = new AsynServer(passiveMerServerConfig);
		passiveMerServer.startListen();
		
		//创建商户(银联主动)客户端连接实例
		ClientConfig passiveMerClientConfig = new ClientConfig(PASSIVE_MERCHAN_CLIENT_KEY);
		passiveMerClientConfig.setHost(PropertyLoader.getInstance().getPassiveMerClientIp());
		passiveMerClientConfig.setPort(PropertyLoader.getInstance().getPassiveMerClientPort());
		passiveMerClientConfig.setCodecFactory(new ClientCodecFactory(PASSIVE_MERCHAN_CLIENT_NAME));
		passiveMerClientConfig.setIoHandlerAdapter(new PassiveMerClientHandler(PASSIVE_MERCHAN_CLIENT_NAME));
		ClientFactory.getInstance().createClient(passiveMerClientConfig);
		
		//启动商户(银盛主动)服务端监听
		ServerConfig activeMerServerConfig = new ServerConfig();
		activeMerServerConfig.setHost(PropertyLoader.getInstance().getLocalIp());
		activeMerServerConfig.setPort(PropertyLoader.getInstance().getActiveMerServerPort());
		activeMerServerConfig.setCodecFactory(new ServerCodecFactory(ACTIVE_MERCHAN_SERVER_NAME));
		activeMerServerConfig.setIoHandlerAdapter(new ActiveMerServerHandler(ACTIVE_MERCHAN_SERVER_NAME));
		activeMerServer = new AsynServer(activeMerServerConfig);
		activeMerServer.startListen();
		
		//创建商户(银盛主动)客户端连接实例
		ClientConfig activeMerClientConfig = new ClientConfig(ACTIVE_MERCHAN_CLIENT_KEY);
		activeMerClientConfig.setHost(PropertyLoader.getInstance().getActiveMerClientIp());
		activeMerClientConfig.setPort(PropertyLoader.getInstance().getActiveMerClientPort());
		activeMerClientConfig.setCodecFactory(new ClientCodecFactory(ACTIVE_MERCHAN_CLIENT_NAME));
		activeMerClientConfig.setIoHandlerAdapter(new ActiveMerClientHandler(ACTIVE_MERCHAN_CLIENT_NAME));
		ClientFactory.getInstance().createClient(activeMerClientConfig);
	}
	
	public void destroyed() throws Exception{
		//等待所有交易处理完成并关闭银联通讯控制器(100 * 100 = 10s)
		stopExpirerMap(chanMessageMap);
		stopExpirerMap(activeMerMessageMap);
		
		ClientFactory.getInstance().destroy();
		chanServer.stopListen();
		passiveMerServer.stopListen();
		activeMerServer.stopListen();
	}

	
	/**
	 * 初始化保存数据的容器
	 * @param map
	 * @throws Exception
	 */
	private void initalizedExpirerMap(ExpiringMap<String, IOMessage> map,ExpirationListener<IOMessage> listener) throws Exception{
		map = new ExpiringMap<String, IOMessage>(GateWayConstant.EXPIRINT_TIMEOUT,
				GateWayConstant.EXPIRINT_INTERVAL);
		map.addExpirationListener(listener);
		map.getExpirer().startExpiring();
	}
	
	/**
	 * 等待所有交易处理完成并关闭银联通讯控制器(100 * 100 = 10s)
	 * @param map
	 * @throws Exception
	 */
	private void stopExpirerMap(ExpiringMap map) throws Exception{
		int waitTimes = 0;
		while(map.size() > 0){
			if(waitTimes > 100){
				break;
			}
			waitTimes++;
			Thread.sleep(100);
		}
		map.clear();
		map.getExpirer().stopExpiring();
	}

	public ExpiringMap<String, IOMessage> getChanMessageMap(){
		return chanMessageMap;
	}

	public ExpiringMap<String, IOMessage> getActiveMerMessageMap() {
		return activeMerMessageMap;
	}
	
	
	/**
	 * 从chanMessageMap响应容器里获得响应
	 * @param key
	 * @return
	 * @throws InterruptedException
	 */
	public IOMessage getChanMessageRsp(String key) throws InterruptedException{
		IOMessage rsp;
		int totalTime = 0;
		while(true){
			Thread.sleep(1000);
			rsp = chanMessageMap.remove(key);
			if(rsp != null){
				break;
			}
			totalTime++;
			if(totalTime > 50){
				break;
			}
		}
		return rsp;
	}
	
	/**
	 * 从activeMerMessageMap响应容器里获得响应
	 * @param key
	 * @return
	 * @throws InterruptedException
	 */
	public IOMessage getActiveMerMessageRsp(String key) throws InterruptedException{
		IOMessage rsp;
		int totalTime = 0;
		while(true){
			Thread.sleep(1000);
			rsp = activeMerMessageMap.remove(key);
			if(rsp != null){
				break;
			}
			totalTime++;
			if(totalTime > 50){
				break;
			}
		}
		return rsp;
	}
}
